package cn.mulanbay.job.web.config;

import cn.mulanbay.business.config.CacheConfig;
import cn.mulanbay.business.handler.HandlerManager;
import cn.mulanbay.business.handler.MessageHandler;
import cn.mulanbay.business.handler.ThreadPoolHandler;
import cn.mulanbay.business.handler.lock.RedisDistributedLock;
import cn.mulanbay.business.processor.ConfigPropertiesProcessor;
import cn.mulanbay.schedule.impl.MybatisPersistentProcessor;
import cn.mulanbay.schedule.impl.ScheduleLockHandler;
import cn.mulanbay.common.json.CustomObjectMapper;
import cn.mulanbay.web.conveter.StringToDateConverter;
import cn.mulanbay.web.conveter.StringToStringConverter;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.support.ConversionServiceFactoryBean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.util.*;

/**
 * SpringMVC相关配置
 *
 * @author fenghong
 * @create 2022-01-16 10:00
 */
@Configuration
public class WebConfig {

    private static final Logger logger = LoggerFactory.getLogger(WebConfig.class);

    /**
     * 解决value设置默认值后无法注入问题
     * @return
     */
    @Primary
    @Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setIgnoreUnresolvablePlaceholders(true);
        return configurer;
    }

    /**
     * 资源文件管理，支持国际化
     *
     * @return
     */
    @Bean
    public ReloadableResourceBundleMessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setDefaultEncoding("utf-8");
        messageSource.setCacheSeconds(120);
        return messageSource;
    }

    /**
     * 配置文件处理
     * @return
     */
    @Bean
    public ConfigPropertiesProcessor configPropertiesProcessor() {
        ConfigPropertiesProcessor pp = new ConfigPropertiesProcessor();
        pp.setIgnoreUnresolvablePlaceholders(true);
        pp.setIgnoreResourceNotFound(true);
        //todo
        pp.setLocations();
        pp.setFileEncoding("utf-8");
        return pp;
    }

    /**
     * 资源文件配置的处理
     * @return
     */
    @Bean
    public MessageHandler messageHandler() {
        return new MessageHandler();
    }

    /**
     * 处理器管理类
     * @return
     */
    @Bean
    public HandlerManager handlerManager() {
        return new HandlerManager();
    }

    /**
     * 线程池处理
     * @return
     */
    @Bean
    public ThreadPoolHandler threadPoolHandler() {
        return new ThreadPoolHandler();
    }

    /**
     * 基于Redis的分布式锁
     * @param redisTemplate
     * @return
     */
    @Bean
    public RedisDistributedLock redisDistributedLock(RedisTemplate redisTemplate) {
        return new RedisDistributedLock(redisTemplate);
    }

    /**
     * 调度锁
     * @return
     */
    @Bean
    public ScheduleLockHandler scheduleLockHandler() {
        return new ScheduleLockHandler();
    }
    /**
     * json处理类
     * @return
     */
    @Primary
    @Bean
    public ObjectMapper objectMapper() {
        logger.debug("初始化objectMapper");
        ObjectMapper objectMapper = new CustomObjectMapper();
        return objectMapper;
    }

    @Primary
    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        //设置日期格式
        mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
        //设置中文编码格式
        List<MediaType> list = new ArrayList<MediaType>();
        list.add(MediaType.APPLICATION_JSON);
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);
        return mappingJackson2HttpMessageConverter;
    }

    @Bean
    public ConversionServiceFactoryBean conversionService() {
        ConversionServiceFactoryBean cs = new ConversionServiceFactoryBean();
        Set<Converter> converters = new HashSet<>();
        converters.add(new StringToDateConverter());
        converters.add(new StringToStringConverter());
        cs.setConverters(converters);
        return cs;
    }

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        //乐观锁
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

    /**
     * 持久实现
     * @return
     */
    @Bean
    public MybatisPersistentProcessor mybatisPersistentProcessor() {
        return new MybatisPersistentProcessor();
    }

    /**
     * 缓存配置
     */
    @Configuration
    public class MyCacheConfig extends CacheConfig {

    }

}
